package com.qingzhou.web.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.qingzhou.framework.aspect.PermissionHolder;
import com.qingzhou.system.domain.SysDictData;
import com.qingzhou.system.service.ISysDictDataService;
import com.qingzhou.web.repository.entity.PatientEntity;
import com.qingzhou.web.service.PatientService;
import com.qingzhou.web.service.StatService;
import com.qingzhou.web.service.impl.params.request.StatPatientForm;
import com.qingzhou.web.service.impl.params.vo.CollectStatVo;
import com.qingzhou.web.service.impl.params.vo.GroupCountVo;
import com.qingzhou.web.service.impl.params.vo.PatientStatVo;
import com.qingzhou.web.service.impl.params.vo.QueueCountsVo;
import com.qingzhou.web.service.util.DictUtil;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class StatServiceImpl implements StatService {
    @Inject
    PatientService patientService;
    @Inject
    ISysDictDataService iSysDictDataService;
    @Override
    public List<PatientStatVo> statPatient(StatPatientForm form) {
        PermissionHolder.setFlag("SKIP");
        try {
            QueryWrapper wrapper = QueryWrapper.create().select("id", "hospital_site", "patient_code", "belonging_group","belong_queue");
            if(StrUtil.isNotEmpty(form.getStartDate())){
                wrapper.ge(PatientEntity::getCreateTime, form.getStartDate());
            }
            if(StrUtil.isNotEmpty(form.getEndDate())){
                wrapper.le(PatientEntity::getCreateTime, form.getEndDate()+" 23:59:59");
            }
            List<PatientEntity> list = patientService.getMapper().selectListByQuery(wrapper);
            Map<String, List<PatientEntity>> patientGroup = list.stream().collect(Collectors.groupingBy(PatientEntity::getHospitalSite));
            // 查有数据的医院
            List<PatientStatVo> voList = this.statWhichHasData(patientGroup,form);

            // 补齐其他无数据的医院
            List<SysDictData> hospitalList = iSysDictDataService.list(QueryWrapper.create().eq("dict_type", "hospital_site_dict"));
            hospitalList.forEach(item->{
                String value = item.getDictValue();
                if(!patientGroup.containsKey(value)){
                    PatientStatVo vo = new PatientStatVo();
                    vo.setHospitalSite(value);
                    vo.setHospitalName(item.getDictLabel());
                    voList.add(vo);
                }
            });

            // 按volist的HospitalSiteName排序
            List<String> order = ListUtil.toList(
                    "北京大学人民医院",
                    "广东省人民医院",
                    "江苏省肿瘤医院",
                    "上海市胸科医院",
                    "山东省肿瘤医院",
                    "中南大学湘雅二医院",
                    "深圳市第三人民医院",
                    "复旦大学附属中山医院",
                    "北京大学第一医院",
                    "武汉协和医院"
            );
            voList.sort(Comparator.comparingInt(o -> {
                int index = order.indexOf(o.getHospitalName());
                return index == -1 ? Integer.MAX_VALUE : index; // 处理不在列表中的情况
            }));
            return voList;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            PermissionHolder.clear();
        }

        return null;
    }

    private List<PatientStatVo> statWhichHasData(Map<String, List<PatientEntity>> patientGroup, StatPatientForm form) {
        // 采集数量
        QueryWrapper collectWrapper = QueryWrapper.create().from("edc_patient").as("ep")
                .leftJoin("edc_collect").as("ec").on("ep.patient_code = ec.patient_code")
                .eq("ec.del_flag","0")
                .select("ep.hospital_site ,ep.patient_code ,ep.belonging_group, ec.omics_type");
        if(StrUtil.isNotEmpty(form.getStartDate())){
            collectWrapper.ge("ep.create_time", form.getStartDate());
        }
        if(StrUtil.isNotEmpty(form.getEndDate())){
            collectWrapper.le("ep.create_time", form.getEndDate()+" 23:59:59");
        }
        List<CollectStatVo> collectList = patientService.getMapper().selectListByQueryAs(collectWrapper, CollectStatVo.class);
        Map<String, List<CollectStatVo>> collectGroup = collectList.stream().collect(Collectors.groupingBy(CollectStatVo::getHospitalSite));

        // 组学采集数量
        QueryWrapper omicsCollectWrapper = QueryWrapper.create().from("edc_patient").as("ep")
                .leftJoin("edc_omics_collect").as("eoc").on("ep.patient_code = eoc.patient_code")
                .eq("eoc.del_flag","0")
                .select("ep.hospital_site ,ep.patient_code ,ep.belonging_group, eoc.omics_type");
        if(StrUtil.isNotEmpty(form.getStartDate())){
            omicsCollectWrapper.ge("ep.create_time", form.getStartDate());
        }
        if(StrUtil.isNotEmpty(form.getEndDate())){
            omicsCollectWrapper.le("ep.create_time", form.getEndDate()+" 23:59:59");
        }
        List<CollectStatVo> omicsList = patientService.getMapper().selectListByQueryAs(omicsCollectWrapper, CollectStatVo.class);
        Map<String, List<CollectStatVo>> omicsGroup = omicsList.stream().collect(Collectors.groupingBy(CollectStatVo::getHospitalSite));

        // vo包装
        List<PatientStatVo> voList = patientGroup.entrySet().stream().map(entry -> {
            String key = entry.getKey();
            List<PatientEntity> value = entry.getValue();
            PatientStatVo vo = new PatientStatVo();
            vo.setHospitalSite(key);
            vo.setHospitalName(DictUtil.getLabel(key,"hospital_site_dict"));
            vo.setPatientCount(new Long(value.size()));
            //干预组患者数量
            List<PatientEntity> intList = value.stream().filter(item -> StrUtil.equals(item.getBelongingGroup(), "INT")).collect(Collectors.toList());
            if(CollUtil.isNotEmpty(intList)){
                vo.setHasGroups(true);
                GroupCountVo groupCountVo = new GroupCountVo();
                groupCountVo.setName("干预组");
                groupCountVo.setPatientCount(new Long(intList.size()));
                vo.getGroups().add(groupCountVo);
            }else{
                vo.setHasGroups(true);
                GroupCountVo groupCountVo = new GroupCountVo();
                groupCountVo.setName("干预组");
                groupCountVo.setPatientCount(0L);
                vo.getGroups().add(groupCountVo);
            }
            //观察组患者数量
            List<PatientEntity> obsList = value.stream().filter(item -> StrUtil.equals(item.getBelongingGroup(), "OBS")).collect(Collectors.toList());//观察组
            if(CollUtil.isNotEmpty(obsList)){
                vo.setHasGroups(true);
                GroupCountVo groupCountVo = new GroupCountVo();
                groupCountVo.setName("观察组");
                groupCountVo.setPatientCount(new Long(obsList.size()));
                vo.getGroups().add(groupCountVo);
            }

            //真实世界组患者数量
            List<PatientEntity> rwgList = value.stream().filter(item -> StrUtil.equals(item.getBelongingGroup(), "RWG")).collect(Collectors.toList());//观察组
            if(CollUtil.isNotEmpty(rwgList)){
                vo.setHasGroups(true);
                GroupCountVo groupCountVo = new GroupCountVo();
                groupCountVo.setName("真实世界组");
                groupCountVo.setPatientCount(new Long(rwgList.size()));
                vo.getGroups().add(groupCountVo);
            }else{
                vo.setHasGroups(true);
                GroupCountVo groupCountVo = new GroupCountVo();
                groupCountVo.setName("真实世界组");
                groupCountVo.setPatientCount(0L);
                vo.getGroups().add(groupCountVo);
            }

            //按队列统计：总量、初始队列、辅助队列、无队列
            QueueCountsVo queueCountsVo = this.buildQueueCounts(value);
            vo.setQueueCounts(queueCountsVo);

            // 按医院查所有患者的ctdna采集和组学数量
            long cSize = 0;
            if(collectGroup.containsKey(key)){
                cSize = collectGroup.get(key).size();
                vo.getOmicsTypeCounts().put("ctDNA-MRD",cSize);
            }
            long oSize = 0;
            if(omicsGroup.containsKey(key)){
                oSize = omicsGroup.get(key).size();
                List<CollectStatVo> collectStatVos = omicsGroup.get(key);
                long fcdnaCount = collectStatVos.stream().filter(item -> StrUtil.equals(item.getOmicsType(), "cfdna")).count();
                vo.getOmicsTypeCounts().put("cfDNA甲基化",fcdnaCount);
                long dxzdbzCount = collectStatVos.stream().filter(item -> StrUtil.equals(item.getOmicsType(), "dxzdbz")).count();
                vo.getOmicsTypeCounts().put("代谢组蛋白组",dxzdbzCount);
            }
            vo.setSampleCount(cSize+oSize);
            return vo;
        }).collect(Collectors.toList());
        return voList;
    }

    private QueueCountsVo buildQueueCounts(List<PatientEntity> value) {
        long total = CollUtil.size(value);
        long initialCount = value.stream().filter(item -> {
            return StrUtil.equals(item.getBelongQueue(), "initial");
        }).count();
        long neoadjuvantCount = value.stream().filter(item -> StrUtil.equals(item.getBelongQueue(), "neoadjuvant")).count();
        long none = total-initialCount-neoadjuvantCount;
        return new QueueCountsVo(total,initialCount,neoadjuvantCount,none);
    }
}
